﻿using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace Accona.Remoting.Remoting
{
    internal class MethodReplySerializer
    {
        private readonly Guid appId;

        public MethodReplySerializer(Guid appId)
        {
            this.appId = appId;
        }

        public DeserializedObject Deserialize(byte[] data)
        {
            var stream = new MemoryStream(data);
            var formatter = new BinaryFormatter();
            var senderId = (Guid) formatter.Deserialize(stream);
            var targetId = (Guid) formatter.Deserialize(stream);
            var callId = (Guid) formatter.Deserialize(stream);
            if (senderId == appId)
                return null;
            if (targetId != appId)
                return null;
            var hasValue = (bool) formatter.Deserialize(stream);
            if (hasValue)
            {
                object methodReturnValue = formatter.Deserialize(stream);
                return new DeserializedObject
                           {
                               Value = methodReturnValue,
                               CallId = callId,
                               SenderId = senderId
                           };
            }
            return null;
        }

        public byte[] Serialize(object obj, Guid targetId, Guid callId)
        {
            var buffer = new byte[1400];
            var stream = new MemoryStream(buffer);
            var formatter = new BinaryFormatter();
            formatter.Serialize(stream, appId);
            formatter.Serialize(stream, targetId);
            formatter.Serialize(stream, callId);
            formatter.Serialize(stream, obj != null);
            if (obj != null)
                formatter.Serialize(stream, obj);
            return buffer;
        }
    }

    public class DeserializedObject
    {
        public Guid SenderId { get; set; }
        public Guid CallId { get; set; }
        public object Value { get; set; }
    }
}